﻿using System;
using System.IO;
using System.Text;

namespace Utils.Buffer
{

    /// <summary>
    /// 字符写入工具
    /// </summary>

    public struct ByteWriteBuffer
    {

        private byte[] bytes;

        private int offset;

        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="capacity">容量</param>
        public ByteWriteBuffer(int capacity = 16)
        {
            bytes = new byte[capacity];
            offset = 0;
        }

        /// <summary>
        /// 写一个
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private int NextAndResize(int length)
        {
            this.offset += length;
            if (this.offset > bytes.Length)
                Array.Resize(ref bytes, Math.Max(bytes.Length * 2, this.offset));
            return this.offset - length;
        }

        /// <summary>
        /// 写入字节数组
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public ByteWriteBuffer Write(byte[] value)
        {
            lock (bytes)
            {
                var off = NextAndResize(value.Length);
                Array.Copy(value, 0, bytes, off, value.Length);
            }
            return this;
        }


        /// <summary>
        /// 写入一个字节
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public ByteWriteBuffer Write(byte value)
        {
            lock (bytes)
            {
                NextAndResize(1);
                bytes[offset] = value;
            }
            return this;
        }

        /// <summary>
        /// 写入int32
        /// </summary>
        /// <param name="value"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public ByteWriteBuffer Write(int value, int length = 4)
        {
            return Write(value.ToBytes(length));
        }
        public ByteWriteBuffer WriteUnknownString(string value, Encoding encoding)
        {
            var bytes = encoding.GetBytes(value);
            Write(bytes.Length);
            return Write(bytes);
        }
        public ByteWriteBuffer WriteUnknownString(string value)
        {
            return WriteUnknownString(value, Encoding.UTF8);
        }

        /// <summary>
        /// 写入int64
        /// </summary>
        /// <param name="value"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public ByteWriteBuffer Write(long value, int length = 8)
        {
            return Write(value.ToBytes(length));
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public ByteWriteBuffer Write(string value)
        {
            return Write(value, Encoding.UTF8);
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="value"></param>
        /// <param name="encoding">编码格式</param>
        /// <returns></returns>
        public ByteWriteBuffer Write(string value, Encoding encoding)
        {
            return Write(encoding.GetBytes(value));
        }


        /// <summary>
        /// 转字节数组
        /// </summary>
        /// <param name="cut">是否裁剪</param>
        /// <returns></returns>
        public byte[] ToBytes(bool cut = true)
        {
            return cut ? bytes.CopyToNew(offset) : bytes;
        }
        /// <summary>
        /// 转字节数组
        /// </summary>
        /// <param name="cut">是否裁剪</param>
        /// <returns></returns>
        public void CopyTo(Stream stearm)
        {
            stearm.Write(bytes, 0, offset);
        }
        /// <summary>
        /// 初始化一个字节写入
        /// </summary>
        /// <param name="capacity"></param>
        /// <returns></returns>
        public static ByteWriteBuffer Alloc(int capacity = 16)
        {
            return new ByteWriteBuffer(capacity);
        }

    }
}
